home *** CD-ROM | disk | FTP | other *** search
- /* +-------------------------------------------------------------------+ */
- /* | Copyright 1993, David Koblas (koblas@netcom.com) | */
- /* | | */
- /* | Permission to use, copy, modify, and to distribute this software | */
- /* | and its documentation for any purpose is hereby granted without | */
- /* | fee, provided that the above copyright notice appear in all | */
- /* | copies and that both that copyright notice and this permission | */
- /* | notice appear in supporting documentation. There is no | */
- /* | representations about the suitability of this software for | */
- /* | any purpose. this software is provided "as is" without express | */
- /* | or implied warranty. | */
- /* | | */
- /* +-------------------------------------------------------------------+ */
-
- #include <stdio.h>
- #include <pwd.h>
- #include <ctype.h>
- #include <X11/Intrinsic.h>
- #include <X11/Xos.h>
- #include <sys/stat.h>
- #include "image.h"
- #include "rc.h"
-
- #ifndef NOSTDHDRS
- #include <stdlib.h>
- #include <unistd.h>
- #endif
-
- extern char *mktemp(char*);
- extern void StrToArgv(char*, int*, char**);
- extern char *GetDefaultRC(void);
-
- #define RC_FILENAME ".XPaintrc"
-
- static String defaultRC[] = {
- #include "DefaultRC.txt.h"
- };
-
- /*
- ** RC File Syntax
- **
- ** brush [ BeginData\n ... \nEndData | filename ]
- **
- ** pattern [ BeginData\n ... \nEndData | filename ]
- **
- ** solid [ name | x-rgb-def | r g b ]
- **
- ** \n# -- comment
- */
-
- #define EQ(a,b) (strcasecmp(a,b) == 0)
-
- static int tempIndex = -1;
- static char *tempName[10];
- static RCInfo *baseInfo = NULL;
-
- static FILE *openTemp(char **np)
- {
- char *n;
- char xx[256];
-
- if ((n = getenv("TMPDIR")) == NULL)
- n = "/tmp";
-
- strcpy(xx, n);
- strcat(xx, "/XPaintXXXXXXX");
- n = mktemp(xx);
- tempName[++tempIndex] = XtNewString(n);
- if (np != NULL)
- *np = tempName[tempIndex];
- return fopen(tempName[tempIndex], "w");
- }
- static void removeTemp()
- {
- if (tempIndex < 0)
- return;
- if (tempName[tempIndex] != NULL) {
- unlink(tempName[tempIndex]);
- XtFree((XtPointer)tempName[tempIndex]);
- }
- tempName[tempIndex--] = NULL;
- }
-
- static void addImage(RCInfo *info, Image *image, Boolean isBrush)
- {
- if (isBrush) {
- info->brushes = (Image**)XtRealloc((XtPointer)info->brushes, (info->nbrushes + 1) * sizeof(Image*));
- info->brushes[info->nbrushes++] = image;
- } else {
- info->images = (Image**)XtRealloc((XtPointer)info->images, (info->nimages + 1) * sizeof(Image*));
- info->images[info->nimages++] = image;
- }
- }
- static void addSolid(RCInfo *info, char *color)
- {
- info->colors = (char**)XtRealloc((XtPointer)info->colors, (info->ncolors + 1) * sizeof(char*));
- info->colors[info->ncolors++] = XtNewString(color);
- }
-
- static RCInfo *makeInfo()
- {
- RCInfo *info;
-
- info = XtNew(RCInfo);
- info->freed = False;
- info->nimages = 0;
- info->nbrushes = 0;
- info->colorFlags = NULL;
- info->colorPixels = NULL;
- info->images = XtNew(Image*);
- info->brushes = XtNew(Image*);
- info->ncolors = 0;
- info->colors = XtNew(char*);
-
- baseInfo = info;
-
- return info;
- }
-
- void FreeRC(RCInfo *info)
- {
- int i;
-
- if (info->colors != NULL) {
- for (i = 0; i < info->ncolors; i++)
- XtFree((XtPointer)info->colors[i]);
- XtFree((XtPointer)info->colors);
- }
- if (info->colorFlags != NULL)
- XtFree((XtPointer)info->colorFlags);
- if (info->colorPixels != NULL)
- XtFree((XtPointer)info->colorPixels);
-
- for (i = 0; i < info->nimages; i++)
- ImageDelete(info->images[i]);
- if (info->images != NULL)
- XtFree((XtPointer)info->images);
-
- for (i = 0; i < info->nbrushes; i++)
- ImageDelete(info->brushes[i]);
- if (info->brushes != NULL)
- XtFree((XtPointer)info->brushes);
-
- XtFree((XtPointer)info);
-
- if (info == baseInfo)
- baseInfo = NULL;
- }
-
-
- static char *expand(char *path)
- {
- static char out[512];
- char name[80];
- char *pp = path, *cp;
- struct passwd *pw;
-
- if (*path != '~')
- return path;
- path++;
- cp = name;
- while (*pp != '/' && *pp != '\0')
- *cp++ = *pp++;
- *cp = '\0';
- if (name[0] == '\0') {
- pw = getpwuid(getuid());
- } else {
- pw = getpwnam(name);
- }
- if (pw == NULL)
- return path;
- strcpy(out, pw->pw_dir);
- strcat(out, "/");
- strcat(out, pp);
-
- return out;
- }
-
- static Boolean readRC(RCInfo **info, char *file)
- {
- FILE *fd = fopen(file, "r");
- char buf[512];
- int lineno = 0;
- int argc;
- char *argv[128 + 2];
-
- if (fd == NULL)
- return False;
-
- while (fgets(buf, sizeof(buf), fd) != NULL) {
- lineno++;
- if (buf[0] == '#' || buf[0] == '!')
- continue;
- StrToArgv(buf, &argc, argv);
- if (argc == 0)
- continue;
- if (EQ(argv[0], "reset")) {
- FreeRC(*info);
- *info = makeInfo();
- } else if (EQ(argv[0], "solid")) {
- addSolid(*info, argv[1]);
- } else if (EQ(argv[0], "pattern") || EQ(argv[0], "brush")) {
- extern Image *ReadMagic(char*);
- char *nm;
- Image *image;
-
- if (EQ(argv[1], "BeginData")) {
- FILE *ofd;
-
- ofd = openTemp(&nm);
- while (fgets(buf, sizeof(buf), fd) != NULL) {
- if (strncmp(buf, "EndData", 7) == 0)
- break;
- if (ofd != NULL)
- fputs(buf, ofd);
- }
- if (ofd != NULL) {
- fclose(ofd);
- } else {
- removeTemp();
- continue;
- }
- } else {
- nm = expand(argv[1]);
- }
-
- if ((image = ReadMagic(nm)) != NULL)
- addImage(*info, image, EQ(argv[0], "brush"));
-
- removeTemp();
- }
- }
-
- return True;
- }
-
- /*
- ** Simple RC reading strategy:
- ** load default
- ** append users ~/.XPaintrc
- ** append users ./.XPaintrc
- **
- */
- RCInfo *ReadDefaultRC()
- {
- static Boolean inited = False;
- static Boolean have[2] = { False, False };
- static time_t lastMtime;
- static RCInfo *info = NULL;
- static char homeRC[256];
- FILE *fd;
- int i;
- char *tn;
- struct passwd *pw = getpwuid(getuid());
- struct stat statbufA, statbufB;
- char *rcf;
-
- if (!inited) {
- inited = True;
- if (pw != NULL && pw->pw_dir != NULL) {
- strcpy(homeRC, pw->pw_dir);
- strcat(homeRC, "/");
- strcat(homeRC, RC_FILENAME);
- } else {
- homeRC[0] = '\0';
- }
- }
-
- if ((rcf = GetDefaultRC()) != NULL) {
- if (stat(rcf, &statbufA) < 0) /* missing file? */
- goto readit;
-
- if (info == NULL || statbufA.st_mtime > lastMtime) {
- info = makeInfo();
- readRC(&info, rcf);
- lastMtime = statbufA.st_mtime;
- }
- } else {
- if (info != NULL) {
- Boolean read = False;
- Boolean hA, hB;
-
- hA = (stat(homeRC, &statbufA) >= 0);
- hB = (stat(RC_FILENAME, &statbufB) >= 0);
-
- if (hA != have[0] || hB != have[1])
- goto readit;
-
- if (hA && statbufA.st_mtime > lastMtime)
- goto readit;
- if (hB && statbufB.st_mtime > lastMtime)
- goto readit;
-
- /*
- ** No change
- */
- return info;
- }
- readit:
- if (info != NULL)
- FreeRC(info);
- info = makeInfo();
-
- /*
- ** Set time information
- */
- have[0] = (stat(homeRC, &statbufA) >= 0);
- have[1] = (stat(RC_FILENAME, &statbufB) >= 0);
-
- if (have[0] && have[1]) {
- if (statbufA.st_mtime > statbufB.st_mtime)
- lastMtime = statbufA.st_mtime;
- else
- lastMtime = statbufB.st_mtime;
- } else if (have[0]) {
- lastMtime = statbufA.st_mtime;
- } else if (have[1]) {
- lastMtime = statbufB.st_mtime;
- }
-
- /*
- ** Load the default RC
- */
- if ((fd = openTemp(&tn)) != NULL) {
- for (i = 0; i < XtNumber(defaultRC); i++) {
- fputs(defaultRC[i], fd);
- putc('\n', fd);
- }
- fclose(fd);
-
- readRC(&info, tn);
- removeTemp();
- }
-
- /*
- ** Load ~/.XPaintrc
- */
- if (homeRC[0] != '\0')
- readRC(&info, homeRC);
-
- /*
- ** Load ".XPaintrc"
- */
- readRC(&info, RC_FILENAME);
- }
-
- if (info->ncolors == 0 && info->nimages == 0) {
- addSolid(info, "black");
- addSolid(info, "white");
- addSolid(info, "red");
- addSolid(info, "green");
- addSolid(info, "blue");
- addSolid(info, "cyan");
- addSolid(info, "magenta");
- addSolid(info, "yellow");
- }
-
- return info;
- }
-
- RCInfo *ReadRC(char *file)
- {
- RCInfo *info = makeInfo();
-
- if (!readRC(&info, file)) {
- /*
- ** Error occured
- */
- FreeRC(info);
- return NULL;
- }
-
- return info;
- }
-